﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security;
using System.Text;
using System.Threading.Tasks;

namespace ServerApp   {


public enum AssociationRegistrationStatus
{ 
    Created,
    AlreadyExist,
    DoesNotExist,
    WrongRegistration,
    SecurityFailure
}

static class AssociationRegistrationHelper
{
    static public AssociationRegistrationStatus RegisterFileAssociation(string fileExtension, string fileType, string exeFullPathName, string friendlyName = "", string iconRelativePath = "")
    {
        //  [HKEY_CLASSES_ROOT\.fileExtension]
        //  @="fileType"
        //
        //  [HKEY_CLASSES_ROOT\fileType]
        //  @="StoreApp Request Workload"
        //
        //  [HKEY_CLASSES_ROOT\fileType\DefaultIcon]
        //  @="%SystemRoot%\\System32\\imageres.dll,-169"
        //
        //  [HKEY_CLASSES_ROOT\fileType\shell]
        //
        //  [HKEY_CLASSES_ROOT\fileType\shell\open]
        //
        //  [HKEY_CLASSES_ROOT\fileType\shell\open\command]
        //  @="\"exeFullPathName\" \"%1\""

        AssociationRegistrationStatus status = AssociationRegistrationStatus.AlreadyExist;
        RegistryKey regKey = null;
        RegistryKey regSubKey = null;
        try
        {
            regKey = Registry.ClassesRoot.OpenSubKey(fileExtension, true);

            // check if the key already exists
            if (regKey == null)
            {
                regKey = Registry.ClassesRoot.CreateSubKey(fileExtension);
                status = AssociationRegistrationStatus.Created;
            }

            // add the link to the file type
            regKey.SetValue("", fileType, RegistryValueKind.String);
            regKey.Close();


            // create the file type subtree
            regKey = Registry.ClassesRoot.OpenSubKey(fileType, true);

            // check if the key already exists
            if (regKey == null)
            {
                regKey = Registry.ClassesRoot.CreateSubKey(fileType);
                status = AssociationRegistrationStatus.Created;
            }

            // add the friendly name of the file type if any
            if (!string.IsNullOrEmpty(friendlyName))
            {
                regKey.SetValue("", friendlyName, RegistryValueKind.String);
                status = AssociationRegistrationStatus.Created;
            }

            // add the icon path if any
            if (!string.IsNullOrEmpty(iconRelativePath))
            {
                regSubKey = regKey.OpenSubKey("DefaultIcon", true);
                if (regSubKey == null)
                {
                    regSubKey = regKey.CreateSubKey("DefaultIcon");
                    status = AssociationRegistrationStatus.Created;
                }

                regSubKey.SetValue("", iconRelativePath, RegistryValueKind.String);
                regSubKey.Close();
            }

            // create the shell\open\command subtree
            regSubKey = regKey.OpenSubKey(@"shell\open\command", true);
            if (regSubKey == null)
            {
                regSubKey = regKey.CreateSubKey(@"shell\open\command");
                status = AssociationRegistrationStatus.Created;
            }
            regSubKey.SetValue("", string.Format("\"{0}\" %1", exeFullPathName));
        }
        catch (UnauthorizedAccessException)
        {
            // we need to be started elevated as Administrator
            return AssociationRegistrationStatus.SecurityFailure;
        }
        catch (SecurityException)
        {
            // we need to be started elevated as Administrator
            return AssociationRegistrationStatus.SecurityFailure;
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.ToString());
        }
        finally
        {
            if (regKey != null)
            {
                regKey.Close();
            }

            if (regSubKey != null)
            {
                regSubKey.Close();
            }
        }

        return status;
    }
    static public AssociationRegistrationStatus CheckFileAssociation(string fileExtension, string fileType, string exeFullPathName)
    {
        //  [HKEY_CLASSES_ROOT\.fileExtension]
        //  @="fileType"
        //
        //  [HKEY_CLASSES_ROOT\fileType]
        //  @="StoreApp Request Workload"
        //
        //  [HKEY_CLASSES_ROOT\fileType\DefaultIcon]
        //  @="%SystemRoot%\\System32\\imageres.dll,-169"
        //
        //  [HKEY_CLASSES_ROOT\fileType\shell]
        //
        //  [HKEY_CLASSES_ROOT\fileType\shell\open]
        //
        //  [HKEY_CLASSES_ROOT\fileType\shell\open\command]
        //  @="\"exeFullPathName\" \"%1\""

        AssociationRegistrationStatus status = AssociationRegistrationStatus.DoesNotExist;
        RegistryKey regKey = null;
        RegistryKey regSubKey = null;
        try
        {
            regKey = Registry.ClassesRoot.OpenSubKey(fileExtension, false);

            // check if the key already exists
            if (regKey == null)
            {
                return status;
            }

            // create the file type subtree
            regKey = Registry.ClassesRoot.OpenSubKey(fileType, false);

            // check if the key already exists
            if (regKey == null)
            {
                return status;
            }

            // create the shell\open\command subtree
            regSubKey = regKey.OpenSubKey(@"shell\open\command");
            if (regSubKey == null)
            {
                return status;
            }
            string sValue = regSubKey.GetValue("") as String;
            if (sValue != null)
            {
                string expectedValue = string.Format("\"{0}\" %1", exeFullPathName);
                if (sValue.CompareTo(expectedValue) == 0)
                {
                    return AssociationRegistrationStatus.AlreadyExist;
                }
                else
                {
                    return AssociationRegistrationStatus.WrongRegistration;
                }
            }
        }
        catch (UnauthorizedAccessException)
        {
            // we need to be started elevated as Administrator
            return AssociationRegistrationStatus.SecurityFailure;
        }
        catch (SecurityException)
        {
            // we need to be started elevated as Administrator
            return AssociationRegistrationStatus.SecurityFailure;
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.ToString());
        }
        finally
        {
            if (regKey != null)
            {
                regKey.Close();
            }

            if (regSubKey != null)
            {
                regSubKey.Close();
            }
        }

        return status;
    }

    static public AssociationRegistrationStatus RegisterProtocolAssociation(string protocol, string exeFullPathName, string friendlyName = "", string iconRelativePath = "")
    {
        // see http://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx for the details
        //
        //  [HKEY_CLASSES_ROOT\protocol]
        //  @="URL:friendlyName"
        //
        //  [HKEY_CLASSES_ROOT\protocol]
        //  "URL Protocol"=""
        //
        //  [HKEY_CLASSES_ROOT\protocol\DefaultIcon]
        //  @="%SystemRoot%\\System32\\imageres.dll,-169"
        //
        //  [HKEY_CLASSES_ROOT\protocol\shell]
        //
        //  [HKEY_CLASSES_ROOT\protocol\shell\open]
        //
        //  [HKEY_CLASSES_ROOT\protocol\shell\open\command]
        //  @="\"exeFullPathName\" \"%1\""

        AssociationRegistrationStatus status = AssociationRegistrationStatus.AlreadyExist;
        RegistryKey regKey = null;
        RegistryKey regSubKey = null;
        try
        {
            regKey = Registry.ClassesRoot.OpenSubKey(protocol, true);

            // check if the key already exists
            if (regKey == null)
            {
                regKey = Registry.ClassesRoot.CreateSubKey(protocol);
                status = AssociationRegistrationStatus.Created;
            }

            // set the URL protocol via the friendly name
            regKey.SetValue("", string.Format("URL:{0}", friendlyName), RegistryValueKind.String);
            regKey.SetValue("URL Protocol", "", RegistryValueKind.String);

            // add the icon path if any
            if (!string.IsNullOrEmpty(iconRelativePath))
            {
                regSubKey = regKey.OpenSubKey("DefaultIcon", true);
                if (regSubKey == null)
                {
                    regSubKey = regKey.CreateSubKey("DefaultIcon");
                    status = AssociationRegistrationStatus.Created;
                }

                regSubKey.SetValue("", iconRelativePath, RegistryValueKind.String);
                regSubKey.Close();
            }

            // create the shell\open\command subtree
            regSubKey = regKey.OpenSubKey(@"shell\open\command", true);
            if (regSubKey == null)
            {
                regSubKey = regKey.CreateSubKey(@"shell\open\command");
                status = AssociationRegistrationStatus.Created;
            }
            regSubKey.SetValue("", string.Format("\"{0}\" %1", exeFullPathName));
        }
        catch (UnauthorizedAccessException)
        {
            // we need to be started elevated as Administrator
            return AssociationRegistrationStatus.SecurityFailure;
        }
        catch (SecurityException)
        {
            // we need to be started elevated as Administrator
            return AssociationRegistrationStatus.SecurityFailure;
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.ToString());
        }
        finally
        {
            if (regKey != null)
            {
                regKey.Close();
            }

            if (regSubKey != null)
            {
                regSubKey.Close();
            }
        }

        return status;
    }
}



}
